package org.audio.tcpspeaker;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.os.Handler;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class MyForegroundServ extends Service {
    private static final int SERVICE_ID = 1;
    private Notification notification;
    public mBinder mbind;
    public Handler h;

    public MyForegroundServ() {
        mbind = new mBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("MyForegroundServ", "开启MyForegroundServ");
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
        notification = new Notification.Builder(this)
                .setContentTitle("TcpSpeaker")
                .setContentText("PCM S16LE CH1 20K")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("MyForegroundServ", "销毁ForegroundService");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("MyForegroundServ", "onBind");
        return mbind;
    }

    //@RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MyForegroundServ", "onStartCommand");
        //判断版本

        if (Build.VERSION.SDK_INT < 18) {//Android4.3以下版本

            //将Service设置为前台服务，可以取消通知栏消息
            startForeground(SERVICE_ID, notification);

        } else if (Build.VERSION.SDK_INT < 28) {//Android4.3 - 7.0之间
            //将Service设置为前台服务，可以取消通知栏消息
            startForeground(SERVICE_ID, notification);
            startService(new Intent(this, InnerService.class));

        } else {
        //Android 8.0以上
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        if (manager != null) {
            NotificationChannel channel = new NotificationChannel("tcp_speaker_channel", "tcp_speaker", NotificationManager.IMPORTANCE_LOW);
            manager.createNotificationChannel(channel);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "tcp_speaker_channel");
            notification = builder.setContentTitle("TcpSpeaker")
                    .setContentText("PCM S16LE CH1 20K")
                    .setWhen(System.currentTimeMillis())
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                    .build();

            //将Service设置为前台服务,Android 8.0 App启动不会弹出通知栏消息，退出后台会弹出通知消息
            //Android9.0启动时候会立刻弹出通知栏消息
            Log.d("MyForegroundServ", "startForeground");
            startForeground(SERVICE_ID, notification);
            }
        }

        return START_STICKY;
    }

    class mBinder extends Binder {
        public connectThread play_thread=null;

        public void connect(String ip, int port) {
            Log.d("MyForegroundServ", "call mBinder.connect");
            if (play_thread==null){
                play_thread = new connectThread(ip, port);
                play_thread.start();
                return;
            } else if (play_thread.step==2) {
                play_thread = new connectThread(ip, port);
                play_thread.start();
                return;
            } else{
                play_thread.showMessage("Doing Connecting , Please Wait.");
                play_thread.updateUI();
                return;
            }
        }

        public void disconnect() {
            play_thread.disconnect();
        }

        public void update_ui() {
            if(play_thread != null) {
                play_thread.updateUI();
            }
        }
    }

    class connectThread extends Thread {
        private Socket sock;
        InputStream inStream;
        String Ip;
        public volatile boolean connected = false;
        int Port;
        public int step=0;

        connectThread(String ip1, int port1) {
            Ip = ip1;
            Port = port1;
        }

        public void updateUI(){
            if(connected) {
                sendStatus("connected");
            }else{
                sendStatus("disconnected");
            }

        }


        public void disconnect() {
            try {
                sock.close();
                sendStatus("disconnected");
                connected = false;
            }catch(IOException e){
                sendStatus("disconnected");
                connected = false;
            }
        }

        public synchronized void sendStatus(String s) {
            Intent itt = new Intent();
            itt.setAction(s);
            getApplicationContext().sendBroadcast(itt);
        }

        public void showMessage(String s) {
            h = new Handler(Looper.getMainLooper());
            h.post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
                }
            });
        }

        @Override
        public void run() {
            try {
                sock = new Socket(Ip, Port);
                sendStatus("connected");
                showMessage("Connected");
                Log.d("connectThread", "Connected");
                connected = true;
                AudioTrack player = null;
                try {
                    inStream = sock.getInputStream();
                    player = new AudioTrack(AudioManager.STREAM_MUSIC, 20000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, 800, AudioTrack.MODE_STREAM);
                    player.play();
                    byte[] buf = new byte[400];
                    int len;
                    step = 1;
                    while (true) {
                        buf = new byte[200];
                        len = inStream.read(buf);
                        if (len > 0) {
                            player.write(buf, 0, len);
                        }
                    }
                } catch (IOException e) {
                    inStream.close();
                    sock.close();
                    sendStatus("disconnected");
                    connected = false;
                    step = 2;
                } finally {
                    player.stop();
                    player.release();
                    step = 2;
                    connected = false;
                }

            } catch (IOException e) {
                sendStatus("disconnected");
                connected = false;
                showMessage("Fail Connect");
                Log.d("connectThread", "Fail Connect");
                step = 2;
            }
        }

    }
    public static class InnerService extends Service {
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            return super.onStartCommand(intent, flags, startId);
        }
    }
}

